package com.tenbent.product.center.example;

import com.tenbent.product.base.action.BaseController;
import com.tenbent.product.base.exception.TenbentException;
import com.tenbent.product.base.exception.TenbentNotFoundException;
import com.tenbent.product.center.user.bo.User;
import com.tenbent.product.center.user.dto.UserDto;
import com.tenbent.product.center.user.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.env.Environment;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 权限测试控制器
 *
 * Created by ThinkPad on 2017/7/24.
 */
@Controller
public class HelloController extends BaseController {

	@Autowired
	Environment env;

	@Autowired
	private PersistentTokenRepository persistentTokenRepository;

	@Autowired
	@Qualifier("userServiceImpl")
	private UserService userService;

	@RequestMapping(value = "/login", method = { RequestMethod.GET, RequestMethod.POST })
	public String login(@RequestParam(value = "error", required = false) String error,
			@RequestParam(value = "logout", required = false) String logout, ModelMap model) throws Exception {

		if (error != null) {
			model.addAttribute("error", StringUtils.isNotEmpty(error) ? error : "Invalid username and password!");
		}
		if (logout != null) {
			model.addAttribute("msg", StringUtils.isNotEmpty(logout) ? logout : "You've been logged out successfully!");
		}
		return "login";
	}

	// 此登出代码也可以不写，security 本身有自带的登出。此处的好处是我们可以控制退出细节
	@RequestMapping(value = "/logout1", method = RequestMethod.GET)
	public String logout1(HttpServletRequest request, HttpServletResponse response) {
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		if (auth != null) {
			SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
			logoutHandler.setClearAuthentication(true);
			logoutHandler.logout(request, response, auth);
			// 删除记住我对应的token记录
			persistentTokenRepository.removeUserTokens(((UserDetails) auth.getPrincipal()).getUsername());
		}
		// Todo 注销是处理逻辑
		// You can redirect wherever you want, but generally it's a good
		// practice to show login screen again.
		return "redirect:/login?logout=logout is ok.";
	}

	@RequestMapping(value = "/hello", method = RequestMethod.GET)
	public String hello(String name) {

		if (StringUtils.isEmpty(name)) {
			throw new TenbentNotFoundException("name is null");
		}
		return "hello";
	}

	@RequestMapping(value = { "/eg/hello" }, method = { RequestMethod.GET, RequestMethod.POST })
	public String helloPage(ModelMap model) {

		model.addAttribute("title", "Spring Security Hello USER");
		model.addAttribute("message", "This is hello page!");
		return "/eg/hello";
	}

	@RequestMapping(value = { "/eg/home" }, method = RequestMethod.GET)
	public String home(ModelMap model) {

		model.addAttribute("user", "Randy");
		return "/eg/home";
	}

	@RequestMapping(value = "/eg/admin", method = { RequestMethod.GET, RequestMethod.POST })
	public String adminPage(ModelMap model) {

		model.addAttribute("title", "Spring Security Hello ADMIN");
		model.addAttribute("message", "This is admin page!");
		return "/eg/admin";
	}

	@RequestMapping(value = "/eg/dba", method = { RequestMethod.GET, RequestMethod.POST })
	public String dbaPage(ModelMap model) {

		model.addAttribute("title", "Spring Security Hello DBA");
		model.addAttribute("message", "This is dba page!");
		return "/eg/dba";
	}

	@RequestMapping(value = "/eg/denied", method = { RequestMethod.GET, RequestMethod.POST })
	public String denied(ModelMap model) {

		model.addAttribute("title", "没有权限");
		model.addAttribute("message", "您没有获取到应有的权限!");
		return "/eg/denied";
	}

	// @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_DBA')")
	@PreAuthorize("isAuthenticated()")
	@RequestMapping(value = "/eg/list", method = RequestMethod.GET)
	public String list(ModelMap model) {
		List<UserDto> users = change.changesToDTOList(userService.getAll(), UserDto.class);
		model.addAttribute("users", users);
		model.addAttribute("user", getPrincipal());
		return "/eg/list";
	}

	@RequestMapping(value = { "/eg/saveUser" }, method = { RequestMethod.GET, RequestMethod.POST })
	public String saveUser(ModelMap model) {

		try {
			/** 此处会报错，因为需要admin身份的用户连接用户 */
			User user = new User("Randy", "123456", "RandyHaha");
			userService.save(user);
		} catch (Exception e) {
			logger.error("此处为了测试方法级security安全，{}", e.getMessage());
			throw new TenbentException(401, "您没有权限！");
		}
		model.addAttribute("title", "Spring Security Hello USER");
		model.addAttribute("message", "This is hello page!");
		return "/eg/hello";
	}

	// 获取当前登录用户
	private String getPrincipal() {

		String userName = "";
		Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		if (principal != null) {
			if (principal instanceof UserDetails) {
				userName = ((UserDetails) principal).getUsername();
			} else {
				userName = principal.toString();
			}
		}
		return userName;
	}
}
